// $codepro.audit.disable numericLiterals, packagePrefixNamingConvention

/**
 * package for all of the controller classes to fit MVC design pattern
 */
package javamonsters.controller;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;
import java.util.Random;

import javamonsters.model.Player;
import javamonsters.model.Ship;
import javamonsters.model.SolarSystem;
import javamonsters.universe.application.UniverseController;
import javamonsters.universe.model.interfaces.UniverseModel;
import javamonsters.view.ConfigView;
import javamonsters.view.MainPanel;
import javamonsters.view.SpaceTraders;

import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;




/**
 * 
 * @author wa
 * @version 1.0
 */
public class ConfigViewController {
	
	/**
	 * booleans to represent whether the correct things have been done
	 * in order for the player to start the game
	 */
	private  boolean nameCheck, difficultyCheck, statCheck;
	
	
	/**
	 * int to represent starting credits amount
	 */
	private final int startingCredits;
	
	/**
	 * Big Decimal to represent starting credits amount
	 */
	private final BigDecimal startingCreditsBD;
	
	/**
	 *  the view for the controller
	 */
	private final ConfigView config;
	
	/**
	 * the main panel that has a card layout that switches between all of the views
	 */
	private final MainPanel card;
	
	/**
	 * keeps a count of how many stat points the player has selected
	 */
	private int statCount = 0;
	
	/**
	 * the sum of all of the stat points that are selected
	 */
	private int statSum;
	
	/**
	 * the fighter stat
	 */
	private int fighterStat;
	
	/**
	 * the engineer stat
	 */
	private int engineerStat;
	
	/**
	 * the pilot stat
	 */
	private int pilotStat;
	
	/**
	 * the trader stat
	 */
	private int traderStat;
	
	/**
	 * the difficulty of the game in String format
	 */
	private String difficulty;
	
	/**
	 * the max value the fighter spinner can have at a given time
	 */
	private int statMaxF;
	
	/**
	 * the max value the engineer spinner can have at a given time
	 */
	private int statMaxE;
	
	/**
	 * the max value the pilot spinner can have at a given time
	 */
	private int statMaxP;
	
	/**
	 * the max value the trader spinner can have at a given time
	 */
	private int statMaxT;
	
	/**
	 * the Player of the game
	 */
	private Player player;
	
	/**
	 * reference to the main controller of the game
	 */
	private final SpaceTraders spaceTraders;
	
	/**
	 * @return string representation of class
	 */
	public String toString() {
		return "Config View Controller";
	}
	
	/**
	 * Constructor for ConfigViewController
	 * 
	 * @param config The config view for this controller
	 * @param card The panel that handles the the switching between panels
	 * @param spaceTraders The main controller for the game
	 */
	public ConfigViewController(ConfigView config, MainPanel card,
		   SpaceTraders spaceTraders) {
		
		this.config = config;
		this.card = card;
		this.spaceTraders = spaceTraders;
		startingCredits = 1000;
		startingCreditsBD = new BigDecimal(startingCredits);
		nameCheck = false;
		difficultyCheck = false;
		statCheck = false;
		//create listeners for buttons and spinners
		config.getBackButton().addActionListener(new BackButtonListener());
		config.getStartButton().addActionListener(new StartButtonListener());
		config.getFighterSpinner().addChangeListener(new SpinnerListener());
		config.getEngineerSpinner().addChangeListener(new SpinnerListener());
		config.getPilotSpinner().addChangeListener(new SpinnerListener());
		config.getTraderSpinner().addChangeListener(new SpinnerListener());
		config.getRadioEasy().addActionListener(new RadioListener("1"));
		config.getRadioNormal().addActionListener(new RadioListener("2"));
		config.getRadioHard().addActionListener(new RadioListener("3"));
		config.getTextField().getDocument().addDocumentListener(new NameListener());

	}
	
	/**
	 * updates the total spinner count and each individual stat count 
	 */
	private void updateStatsAndSums() {
		fighterStat = (Integer) config.getFighterSpinner().getValue();
		engineerStat = (Integer) config.getEngineerSpinner().getValue();
		pilotStat = (Integer) config.getPilotSpinner().getValue();
		traderStat = (Integer) config.getTraderSpinner().getValue();
		statSum = fighterStat + engineerStat + pilotStat + traderStat;
		statCount = statSum;
	}
	
	/**
	 * Checks for any input for the difficulty radio buttons
	 * @author Sami
	 */
	private class RadioListener implements ActionListener {
		/**
		 * String representing the difficulty
		 */
		private final String diff;
		
		/**
		 * Constructor for the radio button listener
		 * 
		 * @param diff A string representing the different difficulties
		 */
		private RadioListener(String diff) {
			this.diff = diff;
		}
		
		/**
		 * delegate responds to difficulty choice
		 * @param e
		 */
		public void actionPerformed(ActionEvent e) {
			
			difficultyCheck = true;
			
			if (diff.equals("1")) {
				difficulty = "easy";
			} else if (diff.equals("2")) {
				difficulty = "normal";
			} else {
				difficulty = "hard";
			}
		}
		
		/**
		 * @return String representation of the radio button listener
		 */
		public String toString() {
			return "radio button listener";
		}
	}
	
	/**
	 * a listener for the spinner determining skill points
	 * @author Sami
	 *
	 */
	private class SpinnerListener implements ChangeListener {
		
		/**
		 * enables the start button once the spinner count is 16
		 * 
		 * @param evt the change event that represents one press of the spinner
		 */
		public void stateChanged(ChangeEvent evt) { 
			updateStatsAndSums();
			final int maxCount = 16;
			if (statCount < maxCount) {
				statMaxF = maxCount;
				statMaxE = maxCount;
				statMaxP = maxCount;
				statMaxT = maxCount;
				statCheck = false;
				config.getStartButton().setEnabled(false);
				
			} else {
				statMaxF = fighterStat;
				statMaxE = engineerStat;
				statMaxP = pilotStat;
				statMaxT = traderStat;
				statCheck = true;
				if (nameCheck && difficultyCheck && statCheck) {
					config.getStartButton().setEnabled(true);
				}
			}
			
			config.getFighterSpinner().setModel(
				   new SpinnerNumberModel(fighterStat, 0, statMaxF, 1));
			((JSpinner.DefaultEditor) config.getFighterSpinner().getEditor()).getTextField().setEditable(false);
			config.getEngineerSpinner().setModel(
				   new SpinnerNumberModel(engineerStat, 0, statMaxE, 1));
			((JSpinner.DefaultEditor) config.getEngineerSpinner().getEditor()).getTextField().setEditable(false);
			config.getPilotSpinner().setModel(
				   new SpinnerNumberModel(pilotStat, 0, statMaxP, 1));
			((JSpinner.DefaultEditor) config.getPilotSpinner().getEditor()).getTextField().setEditable(false);
			config.getTraderSpinner().setModel(
				   new SpinnerNumberModel(traderStat, 0,  statMaxT, 1));
			((JSpinner.DefaultEditor) config.getTraderSpinner().getEditor()).getTextField().setEditable(false);
			
		}
		
		/**
		 * @return String representation of spinner listener
		 */
		public String toString() {
			return "spinner listener";
		}
	}
	
	private class NameListener implements DocumentListener {

		
		public void insertUpdate(DocumentEvent e) {
			if (!config.getTextField().getText().equals("")) {
				nameCheck = true;
				if (nameCheck && difficultyCheck && statCheck) {
					config.getStartButton().setEnabled(true);
				}
			} else {
				nameCheck = false;
				config.getStartButton().setEnabled(false);
			}
		}

		
		public void removeUpdate(DocumentEvent e) {
			if (!config.getTextField().getText().equals("")) {
				nameCheck = true;
				if (nameCheck && difficultyCheck && statCheck) {
					config.getStartButton().setEnabled(true);
				}
			} else {
				nameCheck = false;
				config.getStartButton().setEnabled(false);
			}
		}

		
		public void changedUpdate(DocumentEvent e) {
			if (!config.getTextField().getText().equals("")) {
				nameCheck = true;
				if (nameCheck && difficultyCheck && statCheck) {
					config.getStartButton().setEnabled(true);
				}
			} else {
				nameCheck = false;
				config.getStartButton().setEnabled(false);
			}
		}
		
	}
	
	/**
	 * a button listener for the back button
	 * @author Sami
	 *
	 */
	private class BackButtonListener implements ActionListener {
		//goes to main menu when back button is pressed...need to reset inputted data when back button is pressed
		//so that a fresh screen appears when they press New Game again
		/**
		 * takes the player back to the title screen
		 * @param e
		 */
		public void actionPerformed(ActionEvent e) {
			card.getLayout().show(card, "Main Menu");
		}
		
		/**
		 * @return String representation of back button listener
		 */
		public String toString() {
			return "back button listener";
		}
		
	}
	
	/**
	 * a button listener for the start button
	 * @author Sami
	 *
	 */
	private class StartButtonListener implements ActionListener {
		//creates Player with appropriate stats when Start Game button is pressed
		/**
		 * prints player when new player is instantiated
		 * @param e
		 */
		public void actionPerformed(ActionEvent e) {
				
			player = new Player(config.getTextField().getText(),
					 fighterStat, engineerStat,
					 pilotStat, traderStat, startingCreditsBD,
					 new Ship(Ship.ShipType.FLEA),
					 difficulty);
			// get rid of needless instance variable
			spaceTraders.setPlayer(player);
			final Random rand = new Random();
			final UniverseController universeController = 
				  spaceTraders.getUniverseController();
			
			final UniverseModel universeModel = 
				  universeController.getUniverseModel();
			
			final int randSystem = rand.nextInt(universeController
					  .getUniverseModel().getSolarSystems().size());
			
			final Point location = universeModel.getSolarSystems()
					.get(randSystem).getCoordinates();
			
			final SolarSystem system = universeController.getUniverseModel()
					.getSolarSystems().get(randSystem);
			
			spaceTraders.getPlayer().setCurrLocation(location);
			universeController.setCurrSystem(system);
			
			universeController.getSideView().getSystemLabel()
			.setText(system.getName());
			
			universeController.getSideView().getTechLevelLabel()
			.setText(system.getTechLevel().toString());
			
			universeController.getSideView().getAttributeLabel()
			.setText(system.getAttributes().toString());
			
			final int fuel = spaceTraders.getPlayer().getShip().getFuel();
			
			universeController.getSideView().getCurrentFuelLabel()
			.setText("" + fuel);
			
			universeController.getSideView().getFuelCostLabel()
			.setText("" + 0);
			
			System.out.println(player);
	
			card.getLayout().show(card, "Dual Universe Panel");
		}
		
		/**
		 * @return String representation of start button listener
		 */
		public String toString() {
			return "start button listener";
		}
	}
	

}
